package com.mike.mybatisplus.service;


import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.mike.mybatisplus.dao.StudentMapper;
import com.mike.mybatisplus.pojo.Student;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

/**
 * @ Author     ：mmzs.
 * @ Date       ：Created in  2021/11/27 20:57
 * @ Description：数据库 ( Student ) 业务逻辑层
 */
@Service
public class StudentServiceImpl implements StudentService {

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;
    @Autowired
    private StudentMapper studentMapper;
    // 数据库全部数据
    private List<Student> studentALLData;
    // 数据库名
    private final String tableName = "studentTableData";
    // 数据库 id 记录 （ id = mysql 中 id） #因为 redis 中 map key 不能是 int 类型
    private final String tableId = "id=";

    public Student queryOne (Long id) {
        Student studentData = (Student) redisTemplate.boundHashOps(tableName).get(tableId + id);
        if (studentData != null) {  // 判断数据是否为空
            System.out.println("正在查询的缓存... "+ studentData);
            return studentData;
        }
        System.out.println("正在查询数据库..."+ id);
        return studentMapper.selectById(id);
    }

    public List<Object> queryAll () {
        if (redisTemplate.boundHashOps(tableName).size() == 0) {   // 第一次查询缓存时判断是否有数据
            // 同时进入时在此等待
            synchronized (redisTemplate) {   // 同步锁 解决同时查询数据库（避免造成雪崩）
                // 判断第一次访问数据库的那个人是否留下访问数据
                if (redisTemplate.boundHashOps(tableName).size() == 0) {
                    System.out.println("正在查询数据库...");
                    studentMapper.selectList(Wrappers.query()).forEach((value -> this.additionRedisOne(value)));
                } else {
                    System.out.println("第一次并发时使用缓存 ============================");
                }
            }
        } else {
            System.out.println("正在使用缓存...");
        }
        return redisTemplate.boundHashOps(tableName).values();
    }

    @Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.READ_UNCOMMITTED, rollbackFor = Exception.class, timeout = 5)
    public synchronized boolean additionOne (Student student) {
        // 设置 id
        student.setId((studentMapper.selectCount(Wrappers.query()) + 1));
        System.out.println("正在插入数据库记录 " + student);
        System.out.println(studentMapper.insert(student));
        return this.additionRedisOne(student);
    }

    @Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.READ_UNCOMMITTED, rollbackFor = Exception.class, timeout = 5)
    public synchronized boolean alterOne (Student student) {
        System.out.println("正在修改数据库记录...");
        int i = studentMapper.updateById(student);
        System.out.println("修改数据返回值 "+ i);
        return this.additionRedisOne(student);
    }

    @Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.READ_UNCOMMITTED, rollbackFor = Exception.class, timeout = 5)
    public boolean removeOne (Long id) {
        System.out.println(1/0);
        System.out.println("正在删除数据库： "+ studentMapper.deleteById(id));
        redisTemplate.boundHashOps(tableName).delete(tableId + id);
        return true;
    }

    @Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.READ_UNCOMMITTED, rollbackFor = Exception.class, timeout = 5)
    public boolean additionRedisOne (Student student) {
        System.out.println("正在添加 "+ tableName +" 缓存元素");
        redisTemplate.boundHashOps(tableName).put(this.tableId + student.getId(), student);
        return true;
    }
}
